package com.adv.ems.filters;

import cn.hutool.core.collection.CollectionUtil;
import com.adv.ems.filters.dto.FilterParam;
import com.adv.ems.model.vo.ResultVO;
import org.springframework.stereotype.Component;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class FilterFactory<K, T> {

    private final Map<String, EnergyDataBaseFilter<K, T>> rootBeforeFilterMap;
    private final Map<String, EnergyDataBaseFilter<K, T>> rootAfterFilterMap;

    public FilterFactory(List<EnergyDataBaseFilter<K, T>> filters) {
        rootBeforeFilterMap = new HashMap<>(filters.size());
        rootAfterFilterMap = new HashMap<>(filters.size());
        Map<String, List<EnergyDataBaseFilter<K, T>>> groupFilters = filters.stream().collect(Collectors.groupingBy(EnergyDataBaseFilter::getType));
        for (Map.Entry<String, List<EnergyDataBaseFilter<K, T>>> entry: groupFilters.entrySet()) {
            List<EnergyDataBaseFilter<K, T>> befores = entry.getValue().stream().filter(EnergyDataBaseFilter::isBefore).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(befores)) {
                List<EnergyDataBaseFilter<K, T>> sorted = befores.stream().sorted(Comparator.comparingDouble(this :: getOrder).reversed()).collect(Collectors.toList());
                EnergyDataBaseFilter<K, T> next = null;
                for (EnergyDataBaseFilter<K, T> filter: sorted) {
                    filter.setNext(next);
                    next = filter;
                }
                rootBeforeFilterMap.put(entry.getKey(), sorted.get(sorted.size() - 1));
            }
            List<EnergyDataBaseFilter<K, T>> afters = entry.getValue().stream().filter(f -> !f.isBefore()).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(afters)) {
                List<EnergyDataBaseFilter<K, T>> sorted = afters.stream().sorted(Comparator.comparingDouble(this :: getOrder).reversed()).collect(Collectors.toList());
                EnergyDataBaseFilter<K, T> next = null;
                for (EnergyDataBaseFilter<K, T> filter: sorted) {
                    filter.setNext(next);
                    next = filter;
                }
                rootAfterFilterMap.put(entry.getKey(), sorted.get(sorted.size() - 1));
            }
        }
    }

    public ResultVO<T> doBeforeFilter(List<K> list) {
        return doFilter(rootBeforeFilterMap, list);
    }

    public ResultVO<T> doAfterFilter(List<K> list) {
        return doFilter(rootAfterFilterMap, list);
    }

    private ResultVO<T> doFilter(Map<String, EnergyDataBaseFilter<K, T>> filterMap ,List<K> list) {
        if (CollectionUtil.isEmpty(list)) {
            return ResultVO.success();
        }
        K example = list.get(0);
        if (!filterMap.containsKey(example.getClass().getName())) {
            return ResultVO.success();
        }
        FilterParam<K> param = new FilterParam<>();
        param.setList(list);
        return filterMap.get(example.getClass().getName()).filter(param);
    }

    private Double getOrder(EnergyDataBaseFilter<K, T> f) {
        return f.getOrder();
    }
}
